import { SecuritySettings } from "@zitadel/proto/zitadel/settings/v2/security_settings_pb";

import { headers } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
import { DEFAULT_CSP } from "../constants/csp";
import { getServiceConfig } from "./lib/service-url";
export const config = {
  matcher: ["/.well-known/:path*", "/oauth/:path*", "/oidc/:path*", "/idps/callback/:path*", "/saml/:path*", "/:path*"],
};

async function loadSecuritySettings(request: NextRequest): Promise<SecuritySettings | null> {
  const securityResponse = await fetch(`${request.nextUrl.origin}/security`);

  if (!securityResponse.ok) {
    console.error("Failed to fetch security settings:", securityResponse.statusText);
    return null;
  }

  const response = await securityResponse.json();

  if (!response || !response.settings) {
    console.error("No security settings found in the response.");
    return null;
  }

  return response.settings;
}

export async function middleware(request: NextRequest) {
  // Add the original URL as a header to all requests
  const requestHeaders = new Headers(request.headers);

  // Extract "organization" search param from the URL and set it as a header if available
  const organization = request.nextUrl.searchParams.get("organization");
  if (organization) {
    requestHeaders.set("x-zitadel-i18n-organization", organization);
  }

  // Only run the rest of the logic for the original matcher paths
  const proxyPaths = ["/.well-known/", "/oauth/", "/oidc/", "/idps/callback/", "/saml/"];

  const isMatched = proxyPaths.some((prefix) => request.nextUrl.pathname.startsWith(prefix));

  // Only proxy in self-hosted mode
  if (!isMatched) {
    // For multi-tenant or non-proxied routes, just add the header and continue
    return NextResponse.next({
      request: { headers: requestHeaders },
    });
  }

  const _headers = await headers();
  const { serviceConfig } = getServiceConfig(_headers);

  // add additional headers if available
  if (serviceConfig.publicHost) {
    requestHeaders.set("x-zitadel-public-host", serviceConfig.publicHost);
  }
  if (serviceConfig.instanceHost) {
    requestHeaders.set("x-zitadel-instance-host", serviceConfig.instanceHost);
  }

  const responseHeaders = new Headers();
  responseHeaders.set("Access-Control-Allow-Origin", "*");
  responseHeaders.set("Access-Control-Allow-Headers", "*");

  const securitySettings = await loadSecuritySettings(request);

  if (securitySettings?.embeddedIframe?.enabled) {
    responseHeaders.set(
      "Content-Security-Policy",
      `${DEFAULT_CSP} frame-ancestors ${securitySettings.embeddedIframe.allowedOrigins.join(" ")};`,
    );
    responseHeaders.delete("X-Frame-Options");
  }

  request.nextUrl.href = `${serviceConfig.baseUrl}${request.nextUrl.pathname}${request.nextUrl.search}`;

  return NextResponse.rewrite(request.nextUrl, {
    request: {
      headers: requestHeaders,
    },
    headers: responseHeaders,
  });
}
